/**
 * Winston日志模块
 * 提供强大的日志记录功能，支持多级别、多输出目标
 */

const winston = require('winston');
const fs = require('fs');
const path = require('path');

// 简单直接的配置，使用绝对路径
const logDir = path.join(process.cwd(), 'logs');

// 确保日志目录存在
if (!fs.existsSync(logDir)) {
  fs.mkdirSync(logDir, { recursive: true });
}

// 基本日志格式，确保UTF-8编码
const basicFormat = winston.format.combine(
  winston.format.timestamp(),
  winston.format.printf(({ timestamp, level, message, ...meta }) => {
    // 检查消息类型并适当处理，确保使用UTF-8编码
    let formattedMessage;
    if (typeof message === 'string') {
      // 对于字符串消息，确保正确编码
      // 使用Buffer来确保中文正确编码
      try {
        // 在Windows环境下，确保使用正确的UTF-8编码
        formattedMessage = Buffer.from(message, 'utf8').toString('utf8');
      } catch (error) {
        formattedMessage = message;
      }
    } else {
      // 对于非字符串消息，转换为JSON字符串
      try {
        formattedMessage = JSON.stringify(message, null, 2);
      } catch (error) {
        formattedMessage = '[无法序列化的消息]';
      }
    }
    
    // 如果有额外的元数据，则将其添加到日志中
    let metaString = '';
    if (Object.keys(meta).length > 0) {
      try {
        metaString = JSON.stringify(meta, null, 2);
      } catch (error) {
        metaString = '[无法序列化的元数据]';
      }
    }
    
    // 返回格式化的日志字符串
    return `${timestamp} [Spiritual Insight] ${level}: ${formattedMessage} ${metaString}`.trim();
  })
);

// 专门为文件输出设计的格式，确保UTF-8编码
const fileFormat = winston.format.combine(
  winston.format.timestamp(),
  winston.format.printf(({ timestamp, level, message, ...meta }) => {
    // 确保消息是字符串并且正确编码
    let formattedMessage = '';
    if (typeof message === 'string') {
      // 在Windows环境下，确保使用正确的UTF-8编码
      try {
        formattedMessage = Buffer.from(message, 'utf8').toString('utf8');
      } catch (error) {
        formattedMessage = message;
      }
    } else {
      try {
        formattedMessage = JSON.stringify(message, null, 2);
      } catch (error) {
        formattedMessage = '[无法序列化的消息]';
      }
    }
    
    // 处理元数据
    let metaString = '';
    if (Object.keys(meta).length > 0) {
      try {
        metaString = ' ' + JSON.stringify(meta, null, 2);
      } catch (error) {
        metaString = ' [无法序列化的元数据]';
      }
    }
    
    // 返回格式化的日志字符串，确保UTF-8编码
    return `${timestamp} [Spiritual Insight] ${level}: ${formattedMessage}${metaString}`;
  })
);

// 定义日志配置 - 使用简单配置确保文件创建成功
const loggerConfig = {
  level: process.env.NODE_ENV === 'production' ? 'info' : 'debug',
  format: basicFormat,
  // 移除defaultMeta以简化配置
  transports: [
    // 控制台输出（所有环境都启用以方便调试）
    new winston.transports.Console({
      format: winston.format.combine(
        winston.format.colorize(),
        basicFormat
      )
    }),
    // 所有日志都记录到文件，指定UTF-8编码
    new winston.transports.File({
      filename: path.join(logDir, 'all.log'),
      options: { encoding: 'utf8' }
    }),
    // 错误日志单独记录，指定UTF-8编码
    new winston.transports.File({
      filename: path.join(logDir, 'error.log'),
      level: 'error',
      options: { encoding: 'utf8' }
    })
  ]
};

// 移除自定义文件传输类，回到使用winston内置传输

// 创建Winston日志记录器实例
const logger = winston.createLogger({
  level: process.env.NODE_ENV === 'production' ? 'info' : 'debug',
  format: winston.format.combine(
    winston.format.timestamp(), // 添加时间戳
    winston.format.label({ label: 'Spiritual Insight' }), // 添加标签
    basicFormat // 使用我们定义的基本格式
  ),
  defaultMeta: { service: 'spiritual-insight-service' }, // 默认元数据
  transports: [
    // 控制台输出（所有环境都启用以方便调试）
    new winston.transports.Console({
      format: winston.format.combine(
        winston.format.colorize(),
        basicFormat
      )
    }),
    // 所有日志都记录到文件，指定UTF-8编码
    new winston.transports.File({
      filename: path.join(logDir, 'all.log'),
      format: fileFormat,
      options: { 
        encoding: 'utf8',
        flags: 'a' // 追加模式
      },
      // 确保文件以UTF-8编码创建
      encoding: 'utf8',
      // Windows环境下特殊处理
      eol: '\n',
      // 确保文件以UTF-8 BOM格式创建（在Windows上更兼容）
      openMode: 'a',
      writeFileOptions: {
        encoding: 'utf8',
        flag: 'a'
      }
    }),
    // 开发环境日志记录到development.log文件
    new winston.transports.File({
      filename: path.join(logDir, 'development.log'),
      format: fileFormat,
      level: 'debug',
      options: { 
        encoding: 'utf8',
        flags: 'a' // 追加模式
      },
      // 确保文件以UTF-8编码创建
      encoding: 'utf8',
      // Windows环境下特殊处理
      eol: '\n',
      // 确保文件以UTF-8 BOM格式创建（在Windows上更兼容）
      openMode: 'a',
      writeFileOptions: {
        encoding: 'utf8',
        flag: 'a'
      }
    }),
    // 错误日志单独记录，指定UTF-8编码
    new winston.transports.File({
      filename: path.join(logDir, 'error.log'),
      format: fileFormat,
      level: 'error',
      options: { 
        encoding: 'utf8',
        flags: 'a' // 追加模式
      },
      // 确保文件以UTF-8编码创建
      encoding: 'utf8',
      // Windows环境下特殊处理
      eol: '\n',
      // 确保文件以UTF-8 BOM格式创建（在Windows上更兼容）
      openMode: 'a',
      writeFileOptions: {
        encoding: 'utf8',
        flag: 'a'
      }
    })
  ]
});

// 为了兼容性，添加旧的日志方法
logger.logInfo = logger.info.bind(logger);
logger.logWarning = logger.warn.bind(logger);
logger.logError = logger.error.bind(logger);
logger.logDebug = logger.debug.bind(logger);

/**
 * 记录HTTP请求日志 - 支持原始参数格式
 * @param {string} method - HTTP方法
 * @param {string} url - 请求URL
 * @param {number} statusCode - 状态码
 * @param {number} responseTime - 响应时间(ms)
 * @param {Object} meta - 元数据
 */
logger.logHttpRequest = function(method, url, statusCode, responseTime, meta = {}) {
  try {
    // 兼容旧的调用方式（4个参数）
    if (typeof responseTime === 'object' && !meta) {
      meta = responseTime;
      responseTime = 0;
    }
    
    const level = statusCode >= 500 ? 'error' : 
                 statusCode >= 400 ? 'warn' : 
                 statusCode >= 300 ? 'info' : 'info';
    
    const message = `${method || 'unknown'} ${url || 'unknown'} ${statusCode || 0} ${responseTime || 0}ms`;
    
    // 使用绑定的方法确保正确的上下文
    if (level === 'error' && typeof logger.logError === 'function') {
      logger.logError(message, {
        ...meta,
        method,
        url,
        statusCode,
        responseTime,
        timestamp: new Date().toISOString()
      });
    } else if (level === 'warn' && typeof logger.logWarning === 'function') {
      logger.logWarning(message, {
        ...meta,
        method,
        url,
        statusCode,
        responseTime,
        timestamp: new Date().toISOString()
      });
    } else if (typeof logger.logInfo === 'function') {
      logger.logInfo(message, {
        ...meta,
        method,
        url,
        statusCode,
        responseTime,
        timestamp: new Date().toISOString()
      });
    } else {
      // 最后的降级方案
      console.log(`[Fallback Log] ${message}`, {
        ...meta,
        method,
        url,
        statusCode,
        responseTime,
        timestamp: new Date().toISOString()
      });
    }
  } catch (error) {
    // 使用绑定的方法记录错误
    if (typeof logger.logError === 'function') {
      logger.logError('Error logging HTTP request', { error: error.message });
    } else {
      console.error('Error logging HTTP request', { error: error.message });
    }
  }
};

/**
 * 记录用户活动日志
 * @param {string} userId - 用户ID
 * @param {string} action - 用户操作
 * @param {Object} details - 操作详情
 */
logger.logUserActivity = function(userId, action, details = {}) {
  try {
    this.info('User activity', {
      userId: userId || 'unknown',
      action: action || 'unknown',
      details,
      timestamp: new Date().toISOString()
    });
  } catch (error) {
    this.error('Error logging user activity', { error: error.message });
  }
};

/**
 * 记录系统事件日志
 * @param {string} event - 事件名称
 * @param {Object} data - 事件数据
 */
logger.logSystemEvent = function(event, data = {}) {
  try {
    this.info('System event', {
      event: event || 'unknown',
      data,
      timestamp: new Date().toISOString()
    });
  } catch (error) {
    this.error('Error logging system event', { error: error.message });
  }
};

/**
 * 记录性能指标日志
 * @param {string} operation - 操作名称
 * @param {number} duration - 执行时间(ms)
 * @param {Object} metrics - 性能指标
 */
logger.logPerformanceMetric = function(operation, duration, metrics = {}) {
  try {
    this.info('Performance metric', {
      operation: operation || 'unknown',
      duration: duration || 0,
      metrics,
      timestamp: new Date().toISOString()
    });
  } catch (error) {
    this.error('Error logging performance metric', { error: error.message });
  }
};

// 为保持向后兼容性，增强log方法
logger.log = function(level, message) {
  try {
    if (typeof level === 'string' && !message) {
      // 处理旧的调用方式，如 logger.log('message')
      return this.info(level);
    }
    
    if (typeof level === 'string' && typeof this[level] === 'function') {
      return this[level](message);
    }
    
    return this.info('Unknown log call');
  } catch (error) {
    console.error('Logger method failed:', error);
  }
};

module.exports = logger;